package shell;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TerminalUtil {
    private static ConcurrentHashMap<String, ShellProcess> processMap = new ConcurrentHashMap<String, ShellProcess>();
    private static Map<String, Long> processActiveMillsMap = new HashMap<String, Long>();
    private static final String DEFAULT_ID = "defaultId";
    private static long CHECK_PERIOD_MILLS = 10000;
    private static ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

    public static void main(String[] args) {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String s;
            while ((s = br.readLine()) != null) {
                String ret = null;
                try {
                    ret = runShell(DEFAULT_ID, s);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println(ret);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private static String runShell(String id, String... cmdLines) throws IOException {
        ShellProcess process = getProcess(id);
        OutputStream os = process.getOutputStream();
        for (String cmdLine : cmdLines) {
            os.write(cmdLine.getBytes());
            os.write("\n".getBytes());
        }
        os.flush();
        return process.getResponse();
    }

    private static ShellProcess getProcess(final String id) throws IOException {
        ShellProcess process = processMap.get(id);
        if (process == null) {
            process = new ShellProcess();
            final ShellProcess preProcess = processMap.putIfAbsent(id, process);
            if (preProcess != null) {
                process.destroy();
                process = preProcess;
            } else {
                ses.schedule(getAutoRemoveRunnable(id), CHECK_PERIOD_MILLS, TimeUnit.MILLISECONDS);
            }
        }
        processActiveMillsMap.put(id, System.currentTimeMillis());
        return process;
    }

    private static Runnable getAutoRemoveRunnable(final String id) {
        return new Runnable() {
            @Override
            public void run() {
                Long aLong = processActiveMillsMap.get(id);
                if (aLong == null || System.currentTimeMillis() - aLong >= CHECK_PERIOD_MILLS) {
                    ShellProcess removeProcess = processMap.remove(id);
                    processActiveMillsMap.remove(id);
                    if (removeProcess != null) {
                        removeProcess.destroy();
                        System.out.println("process dead id=" + id);
                    }
                } else {
                    ses.schedule(getAutoRemoveRunnable(id), CHECK_PERIOD_MILLS, TimeUnit.MILLISECONDS);
                }
            }
        };
    }
}